from flask import Flask, request, jsonify, render_template, redirect, url_for, session
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import os
import qrcode
from io import BytesIO
import base64
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime, timedelta
app = Flask(__name__)

# 设置密钥用于会话管理
app.secret_key = 'your-secret-key'  # 请更改为随机且安全的密钥

# 设置数据库文件的绝对路径
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'sign_in.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

# 用户模型，增加角色字段
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), nullable=False, unique=True)
    password_hash = db.Column(db.String(128), nullable=False)
    role = db.Column(db.String(10), nullable=False)  # 'teacher' 或 'student'

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

# 签到会话模型
class SignInSession(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    code = db.Column(db.String(100), nullable=False, unique=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    records = db.relationship('SignInRecord', backref='session', lazy=True)

# 签到记录模型
class SignInRecord(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    student_id = db.Column(db.String(50), nullable=False)
    sign_in_time = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    session_id = db.Column(db.Integer, db.ForeignKey('sign_in_session.id'), nullable=False)

@app.route('/')
def index():
    if 'user_id' in session:
        user = User.query.get(session['user_id'])
        if user.role == 'teacher':
            return redirect(url_for('teacher'))
        elif user.role == 'student':
            return redirect(url_for('student_dashboard'))
    return redirect(url_for('login'))

# 登录页面
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        name = request.form.get('name')
        password = request.form.get('password')
        user = User.query.filter_by(name=name).first()
        if user and user.check_password(password):
            session['user_id'] = user.id
            session['username'] = user.name
            session['role'] = user.role
            if user.role == 'teacher':
                return redirect(url_for('teacher'))
            else:
                return redirect(url_for('student_dashboard'))
        else:
            return render_template('login.html', error='无效的用户名或密码')
    return render_template('login.html')

# 注册页面（可选）
@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        name = request.form.get('name')
        password = request.form.get('password')
        role = request.form.get('role')
        if not name or not password or role not in ['teacher', 'student']:
            return render_template('register.html', error='请填写所有字段并选择有效角色')
        existing_user = User.query.filter_by(name=name).first()
        if existing_user:
            return render_template('register.html', error='用户名已存在')
        new_user = User(name=name, role=role)
        new_user.set_password(password)
        db.session.add(new_user)
        db.session.commit()
        return redirect(url_for('login'))
    return render_template('register.html')

# 登出
@app.route('/logout')
def logout():
    session.clear()
    return redirect(url_for('login'))

# 教师端主页
@app.route('/teacher', methods=['GET', 'POST'])
def teacher():
    if 'user_id' not in session or session.get('role') != 'teacher':
        return redirect(url_for('login'))
    
    if request.method == 'POST':
        code = request.form.get('code')
        if not code:
            return render_template('teacher.html', error='签到码不能为空')
        # 检查签到码是否唯一
        existing_session = SignInSession.query.filter_by(code=code).first()
        if existing_session:
            return render_template('teacher.html', error='签到码已存在，请选择其他码')
        # 创建新的签到会话
        new_session = SignInSession(code=code)
        db.session.add(new_session)
        db.session.commit()
        return redirect(url_for('teacher'))
    
    # 获取最新的签到会话
    session_obj = SignInSession.query.order_by(SignInSession.created_at.desc()).first()
    qr_code = None
    if session_obj:
        # 使用服务器的局域网IP地址
        server_ip = '10.161.20.231'  # 替换为实际的服务器IP地址
        sign_in_url = f'http://{server_ip}:5000/signin?code={session_obj.code}'
        print(f"Sign-in URL: {sign_in_url}")  # 方便调试
        
        # 生成二维码
        qr = qrcode.QRCode(
            version=1,
            box_size=15,  # 增大box_size以提高清晰度
            border=5
        )
        qr.add_data(sign_in_url)
        qr.make(fit=True)
        img = qr.make_image(fill='black', back_color='white')
        buffered = BytesIO()
        img.save(buffered, format="PNG")
        img_str = base64.b64encode(buffered.getvalue()).decode()
        qr_code = img_str
    return render_template('teacher.html', session=session_obj, qr_code=qr_code, error=None)

# 获取教师端签到记录
@app.route('/teacher/records', methods=['GET'])
def teacher_records():
    if 'user_id' not in session or session.get('role') != 'teacher':
        return jsonify({'message': '没有权限访问'}), 403
    # 获取最新的签到会话
    session_obj = SignInSession.query.order_by(SignInSession.created_at.desc()).first()
    if not session_obj:
        return jsonify({'message': '尚未设置签到码'}), 400
    records = SignInRecord.query.filter_by(session_id=session_obj.id).all()
    # 手动添加8小时
    adjusted_records = [{
        'student_id': record.student_id,
        'sign_in_time': (record.sign_in_time + timedelta(hours=8)).strftime('%Y/%m/%d %H:%M:%S')
    } for record in records]
    return jsonify({'records': adjusted_records}), 200

# 学生签到页面（扫码后访问）
@app.route('/signin')
def student_sign_in():
    code = request.args.get('code')
    if not code:
        return "无效的签到链接", 400
    # 检查签到码是否存在
    session_obj = SignInSession.query.filter_by(code=code).first()
    if not session_obj:
        return "无效的签到码", 400
    return redirect(url_for('sign_in', code=code))

# 学生签到
@app.route('/sign_in', methods=['GET', 'POST'])
def sign_in():
    if 'user_id' not in session or session.get('role') != 'student':
        return redirect(url_for('login'))
    
    code = request.args.get('code') if request.method == 'GET' else request.form.get('code')
    if not code:
        return "无效的签到码", 400

    # 检查签到码是否存在
    session_obj = SignInSession.query.filter_by(code=code).first()
    if not session_obj:
        return "无效的签到码", 400

    if request.method == 'POST':
        entered_code = request.form.get('code')
        if entered_code != code:
            return render_template('sign.html', error='签到码不匹配', code=code)
        user_id = session.get('user_id')
        user = User.query.get(user_id)
        if not user:
            return "用户不存在", 400
        # 检查是否已签到
        existing_record = SignInRecord.query.filter_by(student_id=user.name, session_id=session_obj.id).first()
        if existing_record:
            return render_template('sign.html', error='您已经签到过了', code=code)
        # 记录签到
        record = SignInRecord(student_id=user.name, session_id=session_obj.id)
        db.session.add(record)
        db.session.commit()
        return render_template('sign.html', success='签到成功', code=code)
    
    return render_template('sign.html', error=None, code=code)

# 学生仪表盘（查看已签到记录）
@app.route('/student_dashboard', methods=['GET'])
def student_dashboard():
    if 'user_id' not in session or session.get('role') != 'student':
        return redirect(url_for('login'))
    return render_template('student_dashboard.html')

# 获取学生签到记录
@app.route('/records', methods=['GET'])
def get_records():
    if 'user_id' not in session:
        return jsonify({'message': '未登录'}), 401
    # 获取最新的签到会话
    session_obj = SignInSession.query.order_by(SignInSession.created_at.desc()).first()
    if not session_obj:
        return jsonify({'records': []}), 200
    records = SignInRecord.query.filter_by(session_id=session_obj.id).all()
    # 手动添加8小时
    adjusted_records = [{
        'student_id': record.student_id,
        'sign_in_time': (record.sign_in_time + timedelta(hours=8)).strftime('%Y/%m/%d %H:%M:%S')
    } for record in records]
    return jsonify({'records': adjusted_records}), 200

if __name__ == '__main__':
    with app.app_context():
        db.create_all()  # 创建数据库表
    app.run(host='0.0.0.0', port=5000, debug=True)